package oss

import (
	"crypto/md5"
	"fmt"
	"gitee.com/alex_li/zangjingge/internal/db/rdb"
	"github.com/lishimeng/go-log"
	"io"
	"os"
	"path"
	"path/filepath"
	"time"
)

// saveFile 保存文件
//
// docInfo 目标文件信息(保存时)
//
// bucket 存储分区
//
// tempFileMeta 源文件信息(存在缓存分区中)
func saveFile(docInfo rdb.DocInfo, bucket rdb.BucketInfo, tempFileMeta TempFileMeta) (relPath, fullPath string, err error) {
	defer func() {
		//clearTemp(tempFileMeta)
	}()
	// copy file
	//   gen_file_path
	pathWithoutBucket, err := createChildFolder(bucket.RootPath)
	if err != nil {
		return
	}
	savePath := path.Join(GetRootFolder(), bucket.RootPath, pathWithoutBucket, docInfo.Code)

	srcPath := path.Join(GetTempRootFolder(), tempFileMeta.Id, tempFileMeta.Id)
	src, err := os.Open(srcPath)
	if err != nil {
		return
	}
	defer func() {
		_ = src.Close()
	}()
	dest, err := os.OpenFile(savePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		return
	}
	defer func() {
		_ = dest.Close()
	}()
	_, err = io.Copy(dest, src)
	if err != nil {
		return
	}
	log.Info("save file: %s complete", savePath)
	fullPath = savePath
	relPath = path.Join(pathWithoutBucket, docInfo.Code)

	// save to db
	return
}

func checkFileMetaExist(meta TempFileMeta) (exist bool) {
	srcPath := GetMetaFilePath(path.Join(GetTempRootFolder(), meta.Id))
	_, err := os.Stat(srcPath)
	if os.IsNotExist(err) {
		exist = false
		return
	}
	exist = true
	return
}

// 创建文件存储路径(返回全路径, 中间路径已经创建好)
//
// name: 文件名(保存的文件名),
//
// return:
//
// folderPath: bucket之后的路径
func createChildFolder(bucket string) (folderPath string, err error) {
	root := GetRootFolder()
	now := time.Now()
	relPath := genSubPath(bucket, now)
	fullFolder := path.Join(root, bucket, relPath) // 拼接root
	err = os.MkdirAll(fullFolder, 0777)
	if err != nil {
		return
	}
	folderPath = relPath
	return
}

// genSubPath 构建bucket下路径
//
// relPath 不带bucket
//
// fullPath 拼接bucket
func genSubPath(bucket string, now time.Time) (relPath string) {
	a := pathDigest(bucket, now.Format("200601"))
	b := pathDigest(bucket, now.Format("20060102"))
	relPath = path.Join(a, b)
	return
}

func pathDigest(p ...string) (result string) {
	tmp := path.Join(p...)
	h := md5.New()
	h.Write([]byte(tmp))
	bs := h.Sum(nil)
	result = fmt.Sprintf("%02x", bs)
	return
}

func clearTemp(tempFileMeta TempFileMeta) {
	tempRoot := GetTempRootFolder()
	folder := path.Join(tempRoot, tempFileMeta.Id)
	var waitDelete []string
	err := filepath.Walk(folder, func(curPath string, info os.FileInfo, er error) error {
		if er != nil {
			return er
		}
		if folder == curPath {
			return nil
		}
		waitDelete = append(waitDelete, curPath)
		return nil
	})
	if err != nil {
		return
	}
	for _, f := range waitDelete {
		log.Info("remove temp file %s", f)
		err = os.Remove(f)
		if err != nil {
			log.Info("remove temp file %s failed", f)
			log.Info(err)
		}
	}
	log.Info("remove temp folder %s", folder)
	err = os.Remove(folder)
	if err != nil {
		log.Info("remove temp folder %s failed", folder)
		log.Info(err)
	}
}
